package cn.virens.oauth.annotations.config;

import cn.hutool.core.map.MapUtil;
import cn.virens.oauth.annotations.handler.VirAuthAnnotationSource;
import cn.virens.oauth.annotations.handler.VirAuthMethodInterceptor;
import cn.virens.oauth.annotations.handler.VirAuthMethodPointcutAdvisor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.annotation.Role;
import org.springframework.core.Ordered;
import org.springframework.core.type.AnnotationMetadata;

import java.util.Map;

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class VirAuthConfiguration implements ImportAware {
    protected int order = Ordered.LOWEST_PRECEDENCE;

    @Bean("virAuthAnnotationSource")
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public VirAuthAnnotationSource virAuthAnnotationSource() throws Exception {
        return new VirAuthAnnotationSource();
    }

    @Bean("virAuthMethodInterceptor")
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public VirAuthMethodInterceptor virAuthMethodInterceptor() throws Exception {
        VirAuthMethodInterceptor interceptor = new VirAuthMethodInterceptor();
        interceptor.setAnnotationSource(virAuthAnnotationSource());

        return interceptor;
    }

    @Bean("virAuthMethodPointcutAdvisor")
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public VirAuthMethodPointcutAdvisor virAuthMethodPointcutAdvisor() throws Exception {
        VirAuthMethodPointcutAdvisor advisor = new VirAuthMethodPointcutAdvisor();
        advisor.setAnnotationSource(virAuthAnnotationSource());
        advisor.setAdvice(virAuthMethodInterceptor());
        advisor.setOrder(order);

        return advisor;
    }

    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        Map<String, Object> attributes = getAnnotationAttributes(importMetadata);

        this.order = MapUtil.getInt(attributes, "order", Ordered.LOWEST_PRECEDENCE);
    }

    protected Map<String, Object> getAnnotationAttributes(AnnotationMetadata importMetadata) {
        return importMetadata.getAnnotationAttributes(EnableVirAuth.class.getName(), false);
    }

}
